import ReadData as rd
import math
import random
import numpy as np
import scipy.special
INNUM=784     #输入层节点数
HDNUM=100    #隐含层节点数
OUTNUM=10     #输出层节点数
class net:
    def __init__(self):
        #隐藏层，输出层值
        self.hidlayerValue=np.zeros(HDNUM)
        #权重
        self.hidlayerW=np.random.random((INNUM,HDNUM))-0.5
        self.outlayerW=np.random.random((HDNUM,OUTNUM))-0.5
        self.yita = 0.2                               #学习率
        self.b1=random.random()                       #输入层偏置项权重
        self.b2=random.random()                       #隐含层偏置项权重
        self.Tg=np.zeros(OUTNUM)                   #训练目标
        self.O=np.zeros(OUTNUM)                     #网络实际输出
     #前向传播
    def forwardPropagation(self,input):
        #算出隐含层结点的值
            z=np.dot(input,self.hidlayerW)+self.b1
            self.hidlayerValue= scipy.special.expit(z)
            #print(self.hidlayerValue[hNNum])
            #算出输出层结点的值
            z=np.dot(self.hidlayerValue,self.outlayerW)+self.b2
            self.O= scipy.special.expit(z)
            
    def backPropagation(self,T,input):
        #反向传播
        #隐藏层权重更新
        loss=(self.O-T)*self.O*(1-self.O)
        dwho=np.tile(loss,(HDNUM,1))*np.transpose(np.tile(self.hidlayerValue,(OUTNUM,1)))
        self.outlayerW-=self.yita*dwho
        #输入层权重更新
        dwhi_1=np.dot(loss,np.transpose(self.outlayerW))*self.hidlayerValue*(1-self.hidlayerValue)#中间变量
        dwhi=np.tile(dwhi_1,(INNUM,1))*np.transpose(np.tile(input,(HDNUM,1)))
        self.hidlayerW-=self.yita*dwhi
#主程序
mnet=net()
imgs=rd.loadImageSet("train-images.idx3-ubyte");
labels=rd.loadLabelSet("train-labels.idx1-ubyte");
#print(mnet.outlayerW)
for n in range(0,5):
    print(n)
    for x in range(0,60000):
        input=(imgs[x,:]/255*0.99+0.01).ravel() #ravel多维转1维
        target=np.ones(10)*0.01
        target[labels[x]]=0.99
        mnet.forwardPropagation(input)
        mnet.backPropagation(target,input)
Cimgs=rd.loadImageSet("t10k-images.idx3-ubyte")
Clabels=rd.loadLabelSet("t10k-labels.idx1-ubyte")
accurate=0
for x in range(0,1000):
    input=(Cimgs[x,:]/255*0.99+0.01).ravel()
    mnet.forwardPropagation(input)
    list_a = mnet.O.tolist()
    max_index=list_a.index(max(list_a))
    if max_index == Clabels[x]:
        accurate+=1
print(accurate/10)
    
